1 \documentclass[10pt,letterpaper]{article}
3 %---------------------------------------------------------------
4 \usepackage[utf8]{inputenc}
5 \usepackage[spanish]{babel}
7 \usepackage[usenames,dvipsnames]{color}
12 %---------------------------------------------------------------
14 \setlength{\topmargin}{-1.0in}
15 \setlength{\textheight}{9.5in}
16 \setlength{\evensidemargin}{0.0in}
17 \setlength{\oddsidemargin}{0.0in}
18 \setlength{\textwidth}{6.5in}
22 %---------------------------------------------------------------
23 \title{Resumen de algoritmos para torneos de programación}
27 %---------------------------------------------------------------
29 %---------------------------------------------------------------
32 \lstloadlanguages{C++}
33 %---------------------------------------------------------------
34 %---------------------------------------------------------------
35 \section{Teoría de números}
36 %---------------------------------------------------------------
38 \input{./src/number_theory/bigmod}%.tex
40 \subsection{Criba de Eratóstenes}
42 \textbf{Field-testing:}
44 \item \emph{SPOJ} - 2912 - Super Primes
45 \item \emph{Live Archive} - 3639 - Prime Path
49 Marca los números primos en un arreglo. Algunos tiempos de ejecución:
53 SIZE & Tiempo (s) \\ [0.5ex]
58 100000000 & 7.650 \\ [1ex]
63 \input{./src/number_theory/criba}%.tex
65 \subsection{Divisores de un número}
66 Este algoritmo imprime todos los divisores de un número (en desorden) en O($\sqrt{n}$).
67 Hasta 4294967295 (máximo \textit{unsigned long}) responde instantaneamente. Se puede
68 forzar un poco más usando \textit{unsigned long long} pero más allá de $10^{12}$ empieza a
73 \input{./src/number_theory/divisores}%.tex
75 \section{Combinatoria}
76 \subsection{Cuadro resumen}
77 Fórmulas para combinaciones y permutaciones:
79 \renewcommand{\arraystretch}{2} %Multiplica la altura de cada fila de la tabla por 2
80 %Si quiero aumentar el tamaño de una fila en particular insertar \rule{0cm}{1cm} en esa fila.
81 \begin{tabular}{| c | c | c |}
83 \textit{Tipo} & \textit{¿Se permite la repetición?} & \textit{Fórmula} \\ [1.5ex]
86 $r$-permutaciones & No & $ \displaystyle\frac{n!}{(n-r)!} $ \\ [1.5ex]
88 $r$-combinaciones & No & $ \displaystyle\frac{n!}{r!(n-r)!} $ \\ [1.5ex]
90 $r$-permutaciones & Sí & $ \displaystyle n^{r} $ \\
92 $r$-combinaciones & Sí & $ \displaystyle\frac{(n+r-1)!}{r!(n-1)!} $ \\ [1.5ex]
95 \renewcommand{\arraystretch}{1}
97 Tomado de \textit{Matemática discreta y sus aplicaciones}, Kenneth Rosen, 5${}^{\hbox{ta}}$ edición, McGraw-Hill, página 315.
99 \subsection{Combinaciones, coeficientes binomiales, triángulo de Pascal}
100 \emph{Complejidad:} $ O(n^2) $ \\
101 $$ {n \choose k} = \left\{
105 \displaystyle {n - 1 \choose k - 1} + {n - 1 \choose k} & \mbox{en otro caso}\\
110 \input{./src/combinatoria/pascal_triangle}%.tex
113 \textbf{Nota:} $ \displaystyle {n \choose k } $ está indefinido en el código anterior si $ n > k$. ¡La tabla puede estar llena con cualquier basura del compilador!
115 \subsection{Permutaciones con elementos indistinguibles}
116 El número de permutaciones \underline{diferentes} de $n$ objetos, donde hay $n_{1}$ objetos indistinguibles de tipo 1,
117 $n_{2}$ objetos indistinguibles de tipo 2, ..., y $n_{k}$ objetos indistinguibles de tipo $k$, es
119 \frac{n!}{n_{1}!n_{2}! \cdots n_{k}!}
121 \textbf{Ejemplo:} Con las letras de la palabra \texttt{PROGRAMAR} se pueden formar $ \displaystyle \frac{9!}{2! \cdot 3!} =
122 30240 $ permutaciones \underline{diferentes}.
123 \subsection{Desordenes, desarreglos o permutaciones completas}
125 Un desarreglo es una permutación donde ningún elemento $i$ está en la
126 posición $i$-ésima. Por ejemplo, \textit{4213} es un desarreglo de 4 elementos pero
127 \textit{3241} no lo es porque el 2 aparece en la posición 2.
129 Sea $D_{n}$ el número de desarreglos de $n$ elementos, entonces:
134 (n-1)(D_{n-1} + D_{n-2}) & n \geq 2\\
138 Usando el principio de inclusión-exclusión, también se puede encontrar la fórmula
140 D_{n} = n!\left [ 1 - \frac{1}{1!} + \frac{1}{2!} - \frac{1}{3!} + \cdots + (-1)^{n}\frac{1}{n!} \right ]
141 = n! \sum_{i=0}^{n} \frac{(-1)^{i}}{i!}
145 \subsection{Algoritmo de Dijkstra}
146 El peso de todas las aristas debe ser no negativo.
148 \input{./src/grafos/dijkstra}%.tex
150 \subsection{Minimum spanning tree: Algoritmo de Prim}
152 \input{./src/grafos/prim}%.tex
154 \subsection{Minimum spanning tree: Algoritmo de Kruskal + Union-Find}
155 \input{./src/grafos/kruskal}%.tex
157 \subsection{Algoritmo de Floyd-Warshall}
158 \emph{Complejidad:} $ O(n^3) $ \\
159 Se asume que no hay ciclos de costo negativo.
160 \input{./src/grafos/floyd}%.tex
162 \subsection{Algoritmo de Bellman-Ford}
163 Si no hay ciclos de coste negativo, encuentra la distancia más corta entre un nodo
164 y todos los demás. Si sí hay, permite saberlo. \\
165 El coste de las aristas \underline{sí} puede ser negativo.
166 \input{./src/grafos/bellman}%.tex
168 \subsection{Puntos de articulación}
169 \input{./src/grafos/puntos_articulacion}%.tex
171 \subsection{Máximo flujo: Método de Ford-Fulkerson, algoritmo de Edmonds-Karp}
172 El algoritmo de Edmonds-Karp es una modificación al método de Ford-Fulkerson. Este último
173 utiliza DFS para hallar un camino de aumentación, pero la sugerencia de Edmonds-Karp
174 es utilizar BFS que lo hace más eficiente en algunos grafos.
177 \input{./src/grafos/ford_fulkerson}%.tex
179 \section{Programación dinámica}
180 \subsection{Longest common subsequence}
181 \input{./src/dp/lcs}%.tex
183 \subsection{Partición de troncos}
184 Este problema es similar al problema de \textit{Matrix Chain Multiplication}. Se tiene
185 un tronco de longitud $n$, y $m$ puntos de corte en el tronco. Se puede hacer un corte a la vez,
186 cuyo costo es igual a la longitud del tronco. ¿Cuál es el mínimo costo para partir todo el tronco
187 en pedacitos individuales?
190 \textbf{Ejemplo:} Se tiene un tronco de longitud 10. Los puntos de corte son 2, 4, y 7. El mínimo
191 costo para partirlo es 20, y se obtiene así:
193 \item Partir el tronco (0, 10) por 4. Vale 10 y quedan los troncos (0, 4) y (4, 10).
194 \item Partir el tronco (0, 4) por 2. Vale 4 y quedan los troncos (0, 2), (2, 4) y (4, 10).
195 \item No hay que partir el tronco (0, 2).
196 \item No hay que partir el tronco (2, 4).
197 \item Partir el tronco (4, 10) por 7. Vale 6 y quedan los troncos (4, 7) y (7, 10).
198 \item No hay que partir el tronco (4, 7).
199 \item No hay que partir el tronco (7, 10).
200 \item El costo total es $10+4+6 = 20$.
204 El algoritmo es $O(n^3)$, pero optimizable a $O(n^2)$ con una tabla adicional:
205 \input{./src/dp/particion_troncos}%.tex
208 \subsection{Área de un polígono}
209 Si P es un polígono simple (no se intersecta a sí mismo) su área está dada por: \\
211 $ A(P) = \frac{1}{2} \displaystyle\sum_{i=0}^{n-1} (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $ \\
213 \input{./src/geometria/polygon_area}%.tex
215 \subsection{Centro de masa de un polígono}
216 Si P es un polígono simple (no se intersecta a sí mismo) su centro de masa está dado por: \\
218 $ \displaystyle\bar{C}_{x} = \frac{ \displaystyle\iint_{R} x \, dA }{M} = \frac{1}{6M}\sum_{i=1}^{n} (y_{i+1} - y_{i}) (x_{i+1}^2 + x_{i+1} \cdot x_{i} + x_{i}^2) $
222 $\displaystyle\bar{C}_{y} = \frac{ \displaystyle\iint_{R} y \, dA }{M} = \frac{1}{6M} \sum_{i=1}^{n} (x_{i} - x_{i+1}) (y_{i+1}^2 + y_{i+1} \cdot y_{i} + y_{i}^2)$
226 Donde $ M $ es el área del polígono. \\
228 Otra posible fórmula equivalente:
230 $ \displaystyle\bar{C}_{x} = \frac{1}{6A} \sum_{i=0}^{n-1} (x_{i} + x_{i+1}) (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $
234 $ \displaystyle\bar{C}_{y} = \frac{1}{6A} \sum_{i=0}^{n-1} (y_{i} + y_{i+1}) (x_{i} \cdot y_{i+1} - x_{i+1} \cdot y_{i}) $
237 \subsection{Convex hull: Graham Scan}
238 \emph{Complejidad:} $ O(n \log_{2}{n}) $
239 \input{./src/geometria/grahamscan}%.tex
241 \subsection{Convex hull: Andrew's monotone chain}
242 \emph{Complejidad:} $ O(n \log_{2}{n}) $
243 \input{./src/geometria/monotonechain}%.tex
245 \subsection{Mínima distancia entre un punto y un segmento}
246 \input{./src/geometria/distance_point_to_segment}%.tex
248 \subsection{Mínima distancia entre un punto y una recta}
249 \input{./src/geometria/distance_point_to_line}%.tex
251 \subsection{Determinar si un polígono es convexo}
252 \input{./src/geometria/is_convex_polygon}%.tex
254 \subsection{Determinar si un punto está dentro de un polígono convexo}
255 \input{./src/geometria/is_inside_convex_polygon}%.tex
257 \subsection{Determinar si un punto está dentro de un polígono cualquiera}
259 \textbf{Field-testing:}
261 \item \emph{TopCoder} - SRM 187 - Division 2 Hard - PointInPolygon
263 \input{./src/geometria/is_inside_concave_polygon}%.tex
265 %---------------------------------------------------------------
266 \section{Estructuras de datos}
267 \subsection{Árboles de Fenwick ó Binary indexed trees}
269 Se tiene un arreglo $\{a_0, a_1, \cdots, a_{n-1}\}$. Los árboles
270 de Fenwick permiten encontrar $ \displaystyle \sum_{k=i}^{j} a_k $ en orden $O(\log_{2}{n})$ para parejas de $(i, j)$ con $i \leq j$. De la misma manera, permiten sumarle una cantidad a un $a_i$ también en tiempo $O(log_{2}{n})$.
272 \input{./src/estructuras/fenwick}%.tex
274 \subsection{Segment tree}
275 \input{./src/estructuras/segment_tree}%.tex
277 %---------------------------------------------------------------
279 \subsection{El \textit{parser} más rápido del mundo}
281 \item Cada no-terminal: un método
282 \item Cada lado derecho:
284 \item invocar los métodos de los no-terminales o
285 \item Cada terminal: invocar proceso \textit{match}
287 \item Alternativas en una producción: se hace un \textit{if}
290 No funciona con gramáticas recursivas por izquierda ó en las que en algún momento haya
291 varias posibles escogencias que empiezan por el mismo caracter (En ambos casos la gramática se puede factorizar).
294 \textbf{Ejemplo:} Para la gramática:
296 A \longrightarrow (A)A
298 A \longrightarrow \epsilon
301 \input{./src/misc/parser_recursivo_desc}%.tex
305 \subsection{Entrada desde entrada estándar}
306 Este primer método es muy fácil pero es mucho más ineficiente porque utiliza Scanner en vez de BufferedReader: \\
307 \input{./src/java/io_estandar_easy}%.tex
311 Este segundo es más rápido: \\
312 \input{./src/java/io_estandar}%.tex
313 \subsection{Entrada desde archivo}
314 \input{./src/java/io_file}%.tex
316 \subsection{Mapas y sets}
318 \input{./src/java/maps_sets}%.tex
320 La salida de este programa es: \\
323 \fbox{\parbox{2.0in}{
338 \\ \normalfont\normalsize
340 Si quiere usarse una clase propia como llave del mapa o como elemento del set, la clase debe implementar
341 algunos métodos especiales: Si va a usarse un TreeMap ó TreeSet hay que implementar los métodos \texttt{compareTo} y
342 \texttt{equals} de la interfaz \texttt{Comparable} como en la sección \ref{colas_de_prioridad_java}. Si va a usarse
343 un HashMap ó HashSet hay más complicaciones.\\
345 \textbf{Sugerencia:} Inventar una manera de codificar y decodificar la clase en una String o un Integer y meter esa representación en el mapa o set: esas clases ya tienen los métodos implementados.
347 \subsection{Colas de prioridad}
348 \label{colas_de_prioridad_java}
349 Hay que implementar unos métodos. Veamos un ejemplo: \\
350 \input{./src/java/priority_queue}%.tex
352 La salida de este programa es: \\
355 \fbox{\parbox{2.0in}{
356 peso = 0, destino = 12\\
357 peso = 0, destino = 8\\
358 peso = 0, destino = 13\\
359 peso = 3, destino = 7\\
360 peso = 1876, destino = 4\\
363 \\ \normalfont\normalsize
365 Vemos que la función de comparación que definimos no tiene en cuenta \texttt{destino},
366 por eso no desempata cuando dos \texttt{Items} tienen el mismo \texttt{peso} si no que escoge
367 cualquiera de manera arbitraria.
370 \subsection{Entrada desde archivo}
371 \input{./src/c++/io_file}%.tex
373 \subsection{Strings con caractéres especiales}
374 \input{./src/c++/unicode}%.tex
376 \emph{Nota}: Como alternativa a la función getline, se pueden utilizar las funciones fgetws y fputws, y más adelante swscanf y wprintf:
377 \input{./src/c++/fgetws}%.tex